package com.zfzs.post.utils;

import com.alibaba.fastjson.JSONObject;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.domain.AlipayTradeAppPayModel;
import com.alipay.api.request.AlipayFundTransOrderQueryRequest;
import com.alipay.api.request.AlipayFundTransToaccountTransferRequest;
import com.alipay.api.request.AlipayTradeAppPayRequest;
import com.alipay.api.response.AlipayFundTransOrderQueryResponse;
import com.alipay.api.response.AlipayFundTransToaccountTransferResponse;
import com.alipay.api.response.AlipayTradeAppPayResponse;
import com.zfzs.post.exception.BadRequestException;
import com.zfzs.post.modules.domain.AlipayConfig;
import org.apache.commons.collections4.map.HashedMap;

import java.math.BigDecimal;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * 支付宝
 */
public class AliPay {

    public static final String ALI_PAY_TYPE = "alipay";//支付宝
    public static final String ANT_TYPE = "ant";//余额

    public static final String PAYEE_TYPE = "ALIPAY_LOGONID";//支付宝转账类型

    //Map<String,Object> map 是前端传来的参数。解析出来然后放到AlipayTradeAppPayModel里然后在把model对象給request去请求支付宝
    public static String Pay(Map<String, Object> map, AlipayConfig aliPayConfig) {
        String orderStr = "";
        try {
            Map<String, String> orderMap = new LinkedHashMap<>(); // 订单实体
            Map<String, String> bizModel = new LinkedHashMap<>(); // 公共实体
            String body = (String) map.get("body");
            String subject = (String) map.get("subject");
            String order_no = (String) map.get("order_no");
            /****** 2.商品参数封装开始 *****/ // 手机端用
            // 商户订单号，商户网站订单系统中唯一订单号，必填
            orderMap.put("out_trade_no", (String) map.get("order_no"));
            // 订单名称，必填
            orderMap.put("subject", "支付宝支付");
            // 付款金额，必填
            Object amount = map.get("amount");
            String totalAmount = String.valueOf(amount);
            orderMap.put("total_amount", totalAmount);
            // 销售产品码 必填
            orderMap.put("product_code", "QUICK_WAP_PAY");
            /****** --------------- 3.公共参数封装 开始 ------------------------ *****/ // 支付宝用
            // 1.商户appid
            bizModel.put("app_id", aliPayConfig.getAppID());
            // 2.请求网关地址
            bizModel.put("method", aliPayConfig.getGatewayUrl());
            // 3.请求格式
            bizModel.put("format", aliPayConfig.getFormat());
            // 4.回调地址
            bizModel.put("return_url", aliPayConfig.getNotifyUrl());
            // 5.私钥
            bizModel.put("private_key", aliPayConfig.getPrivateKey());
            // 6.商家id
            bizModel.put("seller_id", aliPayConfig.getSysServiceProviderId());
            // 7.加密格式
            bizModel.put("sign_type", aliPayConfig.getSignType() + "");
            /****** --------------- 3.公共参数封装 结束 ------------------------ *****/
            // 实例化客户端
            AlipayClient client = new DefaultAlipayClient(aliPayConfig.getGatewayUrl(), aliPayConfig.getAppID(), aliPayConfig.getPrivateKey(), aliPayConfig.getFormat(), aliPayConfig.getCharset(), aliPayConfig.getPublicKey(), aliPayConfig.getSignType());
            // 实例化具体API对应的request类,类名称和接口名称对应,当前调用接口名称：alipay.trade.app.pay
            AlipayTradeAppPayRequest ali_request = new AlipayTradeAppPayRequest();
            // SDK已经封装掉了公共参数，这里只需要传入业务参数。以下方法为sdk的model入参方式(model和biz_content同时存在的情况下取biz_content)。
            AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();
            // model.setPassbackParams(URLEncoder.encode((String)orderMap.get("body").toString()));;
            // //描述信息 添加附加数据
            model.setBody(body); //商品信息
            model.setSubject(subject); // 商品名称
            model.setOutTradeNo(order_no); // 商户订单号(自动生成)
            model.setTotalAmount(totalAmount); // 支付金额
            model.setProductCode("QUICK_MSECURITY_PAY"); // 销售产品码
            String sellerId = aliPayConfig.getSysServiceProviderId();
            model.setSellerId(sellerId); // 商家id
            ali_request.setBizModel(model);
            String notifyUrl = aliPayConfig.getNotifyUrl();
            ali_request.setNotifyUrl(notifyUrl); // 回调地址
            AlipayTradeAppPayResponse responses = client.sdkExecute(ali_request);
            orderStr = responses.getBody();
            System.out.println(orderStr); // 就是orderString 可以直接给客户端请求，无需再做处理
        } catch (Exception e) {
            e.printStackTrace();
        }
        return orderStr;
    }

    /**
     * 支付宝转账
     *
     * @param aliPayConfig  支付宝应用参数
     * @param orderNo       订单号
     * @param payeeAccount  支付宝账号
     * @param payerRealName 支付宝收款账户姓名
     * @param amount        金额
     * @param remark        备注说明,用来做区分说明 XX平台提现
     */
    public static void aLiTransfer(AlipayConfig aliPayConfig, String orderNo, String payeeAccount, String payerRealName, BigDecimal amount, String remark) {
        Map<String, Object> respMap = new LinkedHashMap<>();
        respMap.put("payee_type", PAYEE_TYPE);
        //订单号
        respMap.put("out_biz_no", orderNo);
        //支付宝账户
        respMap.put("payee_account", payeeAccount);
        //支付宝账户姓名
        respMap.put("payee_real_name", payerRealName);
        //金额
        respMap.put("amount", amount);
        respMap.put("remark", remark);
        String resJson = JSONObject.toJSONString(respMap);
        try {
            AlipayClient alipayClient = new DefaultAlipayClient("https://openapi.alipay.com/gateway.do", aliPayConfig.getAppID(), aliPayConfig.getPrivateKey(), aliPayConfig.getFormat(), aliPayConfig.getCharset(), aliPayConfig.getPublicKey(), aliPayConfig.getSignType());
            AlipayFundTransToaccountTransferRequest request = new AlipayFundTransToaccountTransferRequest();
            request.setBizContent(resJson);
            AlipayFundTransToaccountTransferResponse response = alipayClient.execute(request);
            if (response.isSuccess()) {
                System.out.println("===============调用支付宝转账成功==============");
            } else {
                System.out.println("===============调用支付宝转账失败==============" + response.getSubMsg() + "错误码：" + response.getSubMsg());
                //余额不足时，换个提示
                if ("PAYER_BALANCE_NOT_ENOUGH".equals(response.getSubCode())) {
                    throw new BadRequestException("999", "当前提现人数较多，请稍后再试");
                }
                throw new BadRequestException("999", response.getSubMsg() + "错误码：" + response.getSubMsg());
            }
        } catch (AlipayApiException e) {
            System.out.println("===============调用支付宝转账异常==============" + e.getMessage());
            throw new BadRequestException("999", "调用支付宝转账异常");
        }
    }

    /**
     * 支付宝账单转账查询
     *
     * @param aliPayConfig 支付宝应用参数
     * @param orderNo      订单单号
     * @return map格式code和msg
     */
    public static Map<String, Object> aLiTransferQuery(AlipayConfig aliPayConfig, String orderNo) {
        Map<String, Object> map = new HashedMap();
        Map<String, Object> respMap = new LinkedHashMap<>();
        //订单号
        respMap.put("out_biz_no", orderNo);
        String resJson = JSONObject.toJSONString(respMap);
        try {
            AlipayClient alipayClient = new DefaultAlipayClient(aliPayConfig.getGatewayUrl(), aliPayConfig.getAppID(), aliPayConfig.getPrivateKey(), aliPayConfig.getFormat(), aliPayConfig.getCharset(), aliPayConfig.getPublicKey(), aliPayConfig.getSignType());
            AlipayFundTransOrderQueryRequest request = new AlipayFundTransOrderQueryRequest();
            request.setBizContent(resJson);
            AlipayFundTransOrderQueryResponse response = alipayClient.execute(request);
            if (response.isSuccess()) {
                System.out.println("================查询支付宝转账账单调用成功=============");
                //支付宝订单状态 SUCCESS：成功 FAIL：失败  INIT：等待处理  DEALING：处理中  REFUND：退票 UNKNOWN：未知
                String status = response.getStatus();
                String msg = response.getMsg();
                map.put("code", status);
                map.put("msg", msg);
                return map;
            } else {
                map.put("code", "ERROR");
                map.put("msg", response.getErrorCode() + "-" + response.getFailReason());
                System.out.println("================查询支付宝转账账单调用失败=============" + response.getErrorCode() + "错误码：" + response.getFailReason());
                return map;
            }
        } catch (AlipayApiException e) {
            System.out.println("================查询支付宝转账账单调用异常=============" + e.getMessage());
            return null;
        }
    }
}
